package com.syh.jn.scm.infrastructure.repository.impl.operation.system;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.jn.scm.domain.operation.entity.system.OperationAccount;
import com.syh.jn.scm.domain.operation.repository.system.OperationAccountRepository;
import com.syh.jn.scm.dto.operation.system.account.OperationAccountVo;
import com.syh.jn.scm.infrastructure.repository.model.system.AccountModel;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.stereotype.Repository;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

@Repository
public class OperationAccountRepositoryImpl extends AbstractAggregateRepository<OperationAccount, AccountModel, Long> implements OperationAccountRepository {

  @Override
  protected Class getViewObject() {
    return OperationAccountVo.class;
  }

  @Override
  public Long add(OperationAccount operationAccount) {
    AccountModel accountModel = new AccountModel();
    ExtBeanUtils.copyProperties(operationAccount, accountModel);
    accountModel.setTerminalType("OPERATION");
    return (Long) this.hibernateTemplate.save(accountModel);
  }

  @Override
  public void update(OperationAccount operationAccount) {
    super.update(operationAccount);
  }

  @Override
  protected BaseResolve getViewWrapperResolve(Wrapper wrapper) {
    Map<String, String> params = new HashMap<>();
    params.put("loginAccount", "account.LOGIN_ACCOUNT");
    params.put("businessEntityId", "account.BUSINESS_ENTITY_ID");
    params.put("telephone", "account.TELEPHONE");
    params.put("enable", "account.ENABLE");
    params.put("roleId", "account.ROLE_ID");
    params.put("name", "account.NAME");
    params.put("terminalType", "account.TERMINAL_TYPE");
    params.put("id", "account.ID");
    ResolveToSQL parse = new ResolveToSQL(wrapper, (propertyName) -> {
      return params.get(propertyName);
    });
    return parse;
  }


  @Override
  protected SQL getViewSql() {
    return new SQL() {{
      SELECT(
              SQLAliasGenerateUtil.aliasGenerate(AccountModel.class, "account", null),
              "role.ROLE_NAME AS roleName"
      );
      FROM("T_SYSTEM_ROLE role");
      RIGHT_OUTER_JOIN("T_SYSTEM_ACCOUNT account ON role.ID = account.ROLE_ID ");
    }};
  }

  @Override
  public OperationAccount getOne(Wrapper wrapper) {
    wrapper.append(Restrictions.eq("terminalType", "OPERATION"));
    return super.getOne(wrapper);
  }

  @Override
  public Short getAdminById(Long id) {
    AccountModel model = this.hibernateTemplate.get(AccountModel.class, id);
    if (model != null) {
      return model.getAdmin();
    }
    return null;
  }

  @Override
  public Long getCountByAccountName(String accountName) {
    String hql = "select count(*) from AccountModel model where model.loginAccount = :accountName";
    Query query = this.buildQuery(hql);
    query.setString("accountName", accountName);

    return (Long) query.uniqueResult();
  }

  @Override
  public Long getCountByAccountName(String accountName, Long excludeId) {
    String hql = "select count(*) from AccountModel model where model.loginAccount = :accountName and model.id !=:excludeId";
    Query query = this.buildQuery(hql);
    query.setString("accountName", accountName);
    query.setBigInteger("excludeId", BigInteger.valueOf(excludeId));

    return (Long) query.uniqueResult();
  }
}
